#include <boost/asio.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp>
#include <iostream>

using namespace std;
using namespace boost::asio;
int main(int argc, char *argv[]) {
  try {
    if (argc != 2) {
      std::cerr << "Usage: echo_client <port>\n";
      return 1;
    }
    io_context io;
    boost::asio::signal_set signals(io);
    signals.add(SIGINT);
    signals.add(SIGTERM);
    signals.async_wait([&io](boost::system::error_code, int) { io.stop(); });
    ip::tcp::socket sock(io);
    sock.connect(ip::tcp::endpoint(ip::address::from_string("127.0.0.1"),
                                   atoi(argv[1])));
    char buf[0xFF];
    while (true) {
      std::cout << "######## " << __LINE__ << " #######" << std::endl;
      cin >> buf;
      std::cout << "######## " << __LINE__ << " #######" << std::endl;
      try {
        sock.write_some(buffer(buf, 0xFF));
      } catch (std::exception &e) {
        std::cerr << "Exception: " << e.what() << "\n";
        return 1;
      }
      std::cout << "######## " << __LINE__ << " #######" << std::endl;
      memset(buf, 0, 0xFF);
      try {
        size_t len = 0;
        do {
          sock.read_some(buffer(buf));
          len = strlen(buf);
          std::cout << "######## read len: " << len << __LINE__ << " #######"
                    << std::endl;
        } while (len == 0);
      } catch (std::exception &e) {
        std::cerr << "Exception: " << e.what() << "\n";
        return 1;
      }
      std::cout << "######## " << __LINE__ << " #######" << std::endl;
      cout << buf << endl;
      memset(buf, 0, 0xFF);
    }
    io.run();
    sock.close();
    ::system("pause");
  } catch (std::exception_ptr e) {
    if (e) {
      std::rethrow_exception(e);
      return 1;
    }
  }
  return 0;
}